<?php
namespace soa;

/**
 * 请求服务接口
 *
 * Class apply
 * @package soa
 */
class apply extends client
{
    /**
     * 服务地址
     * @var string
     */
    protected $service_url = 'http://core.kuaidihelp.com/';

    /**
     * 服务名称
     * @var string
     */
    protected $service_name = 'kuaidihelp_core';

    /**
     * 超时时限
     * @var int
     */
    protected $_timeout = 15;

    /**
     * 请求的接口
     * @var
     */
    private $api;

    /**
     * 请求的服务
     * @var
     */
    private $service;

    /**
     * 请求的方法
     * @var
     */
    private $method;

    /**
     * API 版本
     * @var
     */
    private $version;

    /**
     * 发送的数据
     * @var
     */
    private $data;

    /**
     * 输出的内容
     * @var
     */
    private $content;

    /**
     * 请求服务
     *
     * @using \soa\service::service()->apply('core', 'IDCard\getIdentityInfo', ['user_id' => $user_id]);
     * @param $service string
     * @param $api string
     * @param $data array
     * @param $method string
     * @param $version string
     * @return array
     */
    public function apply($service, $api, $data = [], $method = 'post', $version = '')
    {
        if (is_string($data) && !empty($data) && !is_array($data)) {
            return [];
        }

        $this->service = $service;
        $this->api = $api;
        $this->data = $data;
        $this->method = $method;
        $this->version = $version;

        $this->pickConfig();

        $this->patchApi();

        $this->validateMethod();

        $this->playRole();

        $this->outputContent();

        return $this->content;
    }

    /**
     * 拼凑 API
     */
    private function patchApi()
    {
        $api = '/'; // 默认值

        if ($this->api == '/') {
            return ;
        }

        if (!empty($this->api) && is_string($this->api)) {
            $api = preg_replace('`[\\\\]`', '/', $this->api); // 兼容分隔符
            $slash = preg_match('`\?.+\=|\.php`', $api) ? '' : '/'; // 兼容 301
            $version = empty($this->service_version) ? '' : $this->service_version . '/';
            $api = $version . ltrim(trim($api, '/'), $version) . $slash; // 拼接请求地址
        }

        $this->api = $api;
    }

    /**
     * 是否旧 API
     * @return bool
     */
    private function isPrevAPI()
    {
        return $this->service[strlen($this->service) - 1] ? false : true;
    }

    /**
     * 校验请求方法
     */
    private function validateMethod()
    {
        if (!in_array(strtolower($this->method), ['get', 'post', 'put', 'patch', 'delete', 'options'])) {
            $this->method = 'get';
        }
    }

    /**
     * 输出老框架内容
     */
    private function outputContent()
    {
        if ($this->isPrevAPI()) { // 兼容老框架输出方式
            $this->content = is_serialized($this->response) ? unserialize($this->response) : json_decode($this->response, true) ?: ''; // null, false 等情况统一返回 ''
            client::$_error = 0; // 压制新框架解析格式错误
            if (empty($this->content)) {
                // logDebug('url: ' . $this->service_url . ', api: ' . $this->api . ', data: ' . json_encode($this->data) . ', response: ' . $this->response, 'service_apply');
            }
        }
    }

    /**
     * 选取配置项
     */
    private function pickConfig()
    {
        $services = config('service');
        if (isset($services[$this->service])) {
            $this->service_url = $services[$this->service]['service_url'];
            $this->service_name = $services[$this->service]['service_name'];
            $this->service_version = !empty($this->version) ? $this->version : $services[$this->service]['service_version'];
        }
    }
    
    /**
     * 开始请求
     */
    private function playRole()
    {
        $method = $this->method;
        $this->content = $this->$method($this->api, $this->data);
    }

    /**
     * 请求参数校验
     *
     * 简单检验为空情况和兼容驼峰与蛇形写法
     * @param $params string|array
     * @return mixed
     */
    public function validateParams($params)
    {
        if (!is_array($params)) {
            $params = array_map('trim', explode(',', $params));
        }

        $data = json_decode(urldecode(\artisan\input::any('data')), true) ?: \artisan\input::any();

        return array_reduce(array_map(function($param) use ($data) {
            if (isset($data[$param])) {
                return [$param => $data[$param]];
            }

            // 驼峰和蛇形互换
            $result = preg_replace_callback('`[A-Z]|_[a-z]`', function($match) {
                if ($match[0][0] == '_') {
                    return strtoupper($match[0][1]);
                } else {
                    return '_' . strtolower($match[0]);
                }
            }, $param);

            if (isset($data[$result])) {
                return [$param => $data[$result]];
            } else {
                raise(1009, "$param is wrong.");
            }

        }, $params), function($last, $item) {
            return array_merge($last, $item);
        }, []);
    }
}